package com.youi.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.youi.common.Common;
import com.youi.common.DelStatus;
import com.youi.common.OrderStatusEnum;
import com.youi.dao.UserorderDao;
import com.youi.dao.UserwechatDao;
import com.youi.dao.YibaopaymentDao;
import com.youi.entity.User;
import com.youi.entity.Userorder;
import com.youi.entity.Userwechat;
import com.youi.entity.Yibaopayment;
import com.youi.exception.BusinessException;
import com.youi.service.YibaopaymentService;
import com.youi.third.yibaopay.YibaopayUtil;
import com.youi.third.yibaopay.model.CashierdeskResult;
import com.youi.third.yibaopay.model.YibaoorderResult;
import com.youi.util.CommonInfoUtil;
import com.youi.util.JsonUtil;
import com.youi.util.LogUtil;
import com.youi.util.ObjectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class YibaopaymentServiceImpl extends BaseServiceImpl<Yibaopayment> implements YibaopaymentService {

    private YibaopaymentDao yibaopaymentDao;

    @Autowired
    private UserwechatDao userwechatDao;

    @Autowired
    private UserorderDao userorderDao;

    @Autowired
    public void setfaultRecordDao(YibaopaymentDao yibaopaymentDao) {
        this.yibaopaymentDao = yibaopaymentDao;
        super.setBaseDAO(yibaopaymentDao);
    }


    @Transactional
    @Override
    public Yibaopayment payBySerialNumber(String serialNumber, User user, String requestIp) throws BusinessException, IOException {
        Map<String, Object> param = Maps.newHashMap();
        param.put(Common.DELSTATUS, DelStatus.NODEL);
        param.put("serialNumber", serialNumber);
        Yibaopayment yibaopayment = yibaopaymentDao.getObject(param);
        if (yibaopayment == null) {
            throw new BusinessException(CommonInfoUtil.NULLOBJECT, "订单流水信息不存在或被删除");
        }

        param = Maps.newHashMap();
        param.put(Common.DELSTATUS, DelStatus.NODEL);
        param.put(Common.USERID, user.getId());
        Userwechat userwechat = userwechatDao.getObject(param);
        if (userwechat == null) {
            throw new BusinessException(CommonInfoUtil.NULLOBJECT, "微信用户不存在");
        }

        YibaoorderResult createOrderResult = YibaopayUtil.createOrder(yibaopayment.getSerialNumber(), yibaopayment.getPayableAmount());
        if (createOrderResult == null || !"OPR00000".equals(createOrderResult.getCode())) {
            throw new BusinessException(CommonInfoUtil.PARAMERROR, "创建易宝订单失败");
        }
        yibaopayment.setPaymentNo(createOrderResult.getUniqueOrderNo());

        CashierdeskResult cashierdeskResult = YibaopayUtil.getPayUrl(createOrderResult.getToken(), userwechat, requestIp);
        if (cashierdeskResult == null || !"CAS00000".equals(cashierdeskResult.getCode())) {
            throw new BusinessException(CommonInfoUtil.DATAERROR, "调用收银台api失败");
        }
        yibaopayment.setPayData(JsonUtil.toJson(cashierdeskResult.getResultData()));

        yibaopayment.setPayAmount(yibaopayment.getPayableAmount());
        Double serviceCharge = ObjectUtil.sciCal(yibaopayment.getPayAmount() * 0.003, 2);
        Double realAmount = ObjectUtil.sciCal(yibaopayment.getPayAmount() - serviceCharge, 2);
        yibaopayment.setServiceCharge(serviceCharge);
        yibaopayment.setRealAmount(realAmount);
        yibaopayment.setGmtModify(new Date());
        yibaopaymentDao.saveOrUpdate(yibaopayment);

        return yibaopayment;
    }


    @Transactional
    @Override
    public Yibaopayment payByOrderId(Long orderId, User user, String requestIp) throws BusinessException, IOException {
        Map<String, Object> param = Maps.newHashMap();
        param.put(Common.DELSTATUS, DelStatus.NODEL);
        param.put(Common.ID, orderId);
        Userorder userOrder = userorderDao.getObject(param);
        if (userOrder == null) {
            throw new BusinessException(CommonInfoUtil.NULLOBJECT, "订单不存在或被删除");
        }
        //订单必须是待支付才能付款
        if (OrderStatusEnum.TO_PAY.getKey() != userOrder.getStatus()) {
            throw new BusinessException(CommonInfoUtil.NULLOBJECT, "订单不是待付款");
        }

        param = Maps.newHashMap();
        param.put(Common.DELSTATUS, DelStatus.NODEL);
        param.put(Common.USERID, user.getId());
        Userwechat userwechat = userwechatDao.getObject(param);
        if (userwechat == null) {
            throw new BusinessException(CommonInfoUtil.NULLOBJECT, "微信用户不存在");
        }

        //如果是多商家下单，会拆分订单，但是支付单还是同一个，但是在待付款里面去支付的时候，不能再用原来的支付单
        //所以这里要删除本地支付单和易宝支付单，然后再根据拆分后的订单生成支付单
        param = Maps.newHashMap();
        param.put(Common.DELSTATUS, DelStatus.NODEL);
        param.put("serialNumber", userOrder.getTopOrderNo());
        Yibaopayment yibaopayment = yibaopaymentDao.getObject(param);
        if (yibaopayment != null) {
            //删除本地支付单和易宝订单
            JSONObject jsonObject = YibaopayUtil.getYibaoorder(yibaopayment.getSerialNumber(), yibaopayment.getPaymentNo());
            if (jsonObject != null && "OPR00000".equals(jsonObject.getString("code"))) {
                if (jsonObject.getString("status").equals("SUCCESS")) {
                    userOrder.setStatus(OrderStatusEnum.PAYED.getKey());
                    userOrder.setGmtPay(new Date());
                    userorderDao.saveOrUpdate(userOrder);
                    return yibaopayment;
                } else if (jsonObject.getString("status").equals("PROCESSING")) {
                    JSONObject closeOrderData = YibaopayUtil.yibaoCloseOrder(yibaopayment.getSerialNumber(), yibaopayment.getPaymentNo(), "订单取消支付");
                    LogUtil.Info("****待支付订单支付****拆分订单关闭原来的易宝订单****" + JsonUtil.toJson(closeOrderData));
                }
            }
            yibaopaymentDao.delById(yibaopayment.getId());
        }

        //重新根据订单创建本地支付单
        String serialNumber = ObjectUtil.getOrderNo(0, user.getId().toString());
        yibaopayment = new Yibaopayment(user.getId(), serialNumber, userOrder.getPayableAmount());
        yibaopayment.setOrderNos(userOrder.getOrderNo());

        //创建易宝订单
        YibaoorderResult createOrderResult = YibaopayUtil.createOrder(yibaopayment.getSerialNumber(), yibaopayment.getPayableAmount());
        if (createOrderResult == null || !"OPR00000".equals(createOrderResult.getCode())) {
            throw new BusinessException(CommonInfoUtil.PARAMERROR, "创建易宝订单失败");
        }
        yibaopayment.setPaymentNo(createOrderResult.getUniqueOrderNo());

        CashierdeskResult cashierdeskResult = YibaopayUtil.getPayUrl(createOrderResult.getToken(), userwechat, requestIp);
        if (cashierdeskResult == null || !"CAS00000".equals(cashierdeskResult.getCode())) {
            throw new BusinessException(CommonInfoUtil.DATAERROR, "调用收银台api失败");
        }
        yibaopayment.setPayData(JsonUtil.toJson(cashierdeskResult.getResultData()));

        yibaopayment.setPayAmount(yibaopayment.getPayableAmount());
        Double serviceCharge = ObjectUtil.sciCal(yibaopayment.getPayAmount() * 0.003, 2);
        Double realAmount = ObjectUtil.sciCal(yibaopayment.getPayAmount() - serviceCharge, 2);
        yibaopayment.setRealAmount(realAmount);
        yibaopayment.setServiceCharge(serviceCharge);
        yibaopayment.setGmtModify(new Date());
        yibaopaymentDao.saveOrUpdate(yibaopayment);

        //更新订单topOrderNo
        userOrder.setTopOrderNo(yibaopayment.getSerialNumber());
        userOrder.setGmtModify(new Date());
        userorderDao.saveOrUpdate(userOrder);

        return yibaopayment;
    }

    @Transactional
    @Override
    public void callBackForMiniApp(String serialNumber, String uniqueOrderNo) throws BusinessException, IOException {
        LogUtil.Info("****前端支付回调****Start****");
        JSONObject jsonObject = YibaopayUtil.getYibaoorder(serialNumber, uniqueOrderNo);
        if (jsonObject == null || !"OPR00000".equals(jsonObject.getString("code"))) {
            LogUtil.Error("****前端支付回调****" + jsonObject.getString("message") + "****");
            return;
        }
        if (!"SUCCESS".equals(jsonObject.get("status"))) {
            LogUtil.Error("****前端支付回调****" + jsonObject.getString("status") + "****");
            return;
        }

        Map<String, Object> param = Maps.newHashMap();
        param.put(Common.DELSTATUS, DelStatus.NODEL);
        param.put("serialNumber", serialNumber);
        Yibaopayment yibaopayment = yibaopaymentDao.getObject(param);
        if (yibaopayment == null) {
            LogUtil.Error("****前端支付回调****本地支付单不存在****");
            return;
        }

        param = new HashMap<String, Object>();
        param.put(Common.DELSTATUS, DelStatus.NODEL);
        param.put("topOrderNo", yibaopayment.getSerialNumber());
        List<Userorder> userOrderList = userorderDao.getObjectList(param);
        if (CollectionUtils.isEmpty(userOrderList)) {
            LogUtil.Error("****前端支付回调****本地支付单下没有订单****");
            return;
        }

        userOrderList.stream().forEach(userOrder -> {
            if (userOrder.getStatus() == OrderStatusEnum.TO_PAY.getKey()) {
                userOrder.setStatus(OrderStatusEnum.PAYED.getKey());
                userOrder.setGmtPay(new Date());
                userorderDao.saveOrUpdate(userOrder);
                LogUtil.Info("****前端支付回调****订单号:" + userOrder.getOrderNo() + "****状态从待支付改为待发货****");
            }
        });
        LogUtil.Info("********前端支付回调****End****");
    }
}